package com.ydlclass.loadbnlancer.impl;

import com.ydlclass.YrpcBootstrap;
import com.ydlclass.discovery.Registry;
import com.ydlclass.exceptions.LoadBalancerException;
import com.ydlclass.loadbnlancer.AbstractLoadBalance;
import com.ydlclass.loadbnlancer.LoadBalancer;
import com.ydlclass.loadbnlancer.Selector;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 轮询的loadBalance策略
 * @Author duWenJian
 * @Date 2023/11/4 13:47
 * @Version 1.0
 */
@Slf4j
public class RoundRobinLoadBalancer extends AbstractLoadBalance {


    /**
     * private Registry registry;
     *     // 缓存
     *     private Map<String,Selector> cache = new ConcurrentHashMap<>(8);
     *
     *     public RoundRobinLoadBalancer() {
     *         this.registry = YrpcBootstrap.getInstance().getRegistry();
     *     }
     *
     *     @Override
     *     public InetSocketAddress selectServiceAddress(String serviceName) {
     *         Selector selector = cache.get(serviceName);
     *         // 缓存中没有,自己创建
     *         if (selector == null ){
     *             // todo 对于一个负载均衡器，内部应该维护一个服务列表作为缓存
     *             List<InetSocketAddress> addressesList = this.registry.lookup(serviceName);
     *             // todo 提供一些算法负责选取合适的节点
     *             selector = new RoundRobinSelector(addressesList);
     *             cache.put(serviceName,selector);
     *         }
     *         // 获取可用节点
     *         return selector.getNext();
     *     }
     */

    @Override
    protected Selector getSelector(List<InetSocketAddress> serviceList) {
        return new RoundRobinSelector(serviceList);
    }

    private static class RoundRobinSelector implements Selector{

        private List<InetSocketAddress> serviceList;
        // 游标指针
        private AtomicInteger index;

        public RoundRobinSelector(List<InetSocketAddress> serviceList) {
            this.serviceList = serviceList;
            this.index = new AtomicInteger(0);
        }

        @Override
        public InetSocketAddress getNext() {
            if (serviceList == null || serviceList.size() == 0){
                log.error("选取节点服务列表为空");
                throw new LoadBalancerException("服务列表为空");
            }
            // 轮询算法
            InetSocketAddress address = serviceList.get(index.get());
            // 循环到最后一个服务，重新开始
            if (index.get() == serviceList.size() - 1){
                index.set(0);
            } else {
                // 游标指针+1
                index.incrementAndGet();
            }
            return address;
        }
    }
}
